#include "mainwindow.h"
#include <QList>
#include <QSerialPortInfo>
#include <QLabel>
#include <QMessageBox>
#include <QLineEdit>

#include "aboutdialog.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      m_toolBar(nullptr),
      m_serialPort(nullptr)
{
    setWindowIcon(QIcon(":/images/main.ico"));
    resize(1024, 1024);

    m_toolBar = new QToolBar(this);
    m_toolBar->setMovable(false);

    // Port ComboBox

    QLabel* label = new QLabel(tr("Port"));
    label->setStyleSheet("QLabel {margin-left: 5px; margin-right: 3px}");
    m_toolBar->addWidget(label);

    m_cbxPortList = new QComboBox(m_toolBar);
    m_cbxPortList->setFixedWidth(100);

    QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
    foreach (QSerialPortInfo port, ports) {
        m_cbxPortList->addItem(port.portName());
    }

    m_toolBar->addWidget(m_cbxPortList);

    // Baudrate Combobox

    label = new QLabel(tr("Baudrate"));
    label->setStyleSheet("QLabel {margin-left: 10px; margin-right: 5px;}");
    m_toolBar->addWidget(label);

    m_cbxBaudrateList = new QComboBox(m_toolBar);
    m_cbxBaudrateList->addItems({"1200", "2400", "4800", "9600", "19200", "38400", "57600", "115200"});
    m_cbxBaudrateList->setCurrentText("115200");
    m_toolBar->addWidget(m_cbxBaudrateList);

    // DataBits ComboBox

    label = new QLabel(tr("DataBits"));
    label->setStyleSheet("QLabel {margin-left: 10px; margin-right: 5px;}");
    m_toolBar->addWidget(label);

    m_cbxDataBitsList = new QComboBox(m_toolBar);
    m_cbxDataBitsList->addItems({"5", "6", "7", "8"});
    m_cbxDataBitsList->setCurrentText("8");
    m_toolBar->addWidget(m_cbxDataBitsList);

    // Parity ComboBox

    label = new QLabel(tr("Parity"));
    label->setStyleSheet("QLabel {margin-left: 10px; margin-right: 5px;}");
    m_toolBar->addWidget(label);

    m_cbxParityList = new QComboBox(m_toolBar);
    m_cbxParityList->addItem("None", QVariant(QSerialPort::NoParity));
    m_cbxParityList->addItem("Even", QVariant(QSerialPort::EvenParity));
    m_cbxParityList->addItem("Odd", QVariant(QSerialPort::OddParity));
    m_cbxParityList->addItem("Mark", QVariant(QSerialPort::MarkParity));
    m_cbxParityList->addItem("Space", QVariant(QSerialPort::SpaceParity));
    m_cbxParityList->setCurrentIndex(0);
    m_toolBar->addWidget(m_cbxParityList);

    // StopBits ComboBox

    label = new QLabel(tr("StopBits"));
    label->setStyleSheet("QLabel {margin-left: 10px; margin-right: 5px;}");
    m_toolBar->addWidget(label);

    m_cbxStopBitsList = new QComboBox(m_toolBar);
    m_cbxStopBitsList->addItem("1", QVariant(QSerialPort::OneStop));
    m_cbxStopBitsList->addItem("1.5", QVariant(QSerialPort::OneAndHalfStop));
    m_cbxStopBitsList->addItem("2", QVariant(QSerialPort::TwoStop));
    m_cbxStopBitsList->setCurrentIndex(0);
    m_toolBar->addWidget(m_cbxStopBitsList);

    m_openAction = m_toolBar->addAction("Open", this, &MainWindow::onOpen);
    addToolBar(m_toolBar);

    QWidget *spacer = new QWidget(m_toolBar);
    spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_toolBar->addWidget(spacer);

    m_toolBar->addAction("?", [](){
        AboutDialog().exec();
    });

    // status bar
    m_statusBar = new QStatusBar(this);

    m_lblAttitude = new QLabel(m_statusBar);
    m_statusBar->addWidget(m_lblAttitude);

    setStatusBar(m_statusBar);

    m_myOpenGLWidget = new MyOpenGLWidget(this);
    setCentralWidget(m_myOpenGLWidget);

    m_serialPort = new QSerialPort(this);
    connect(m_serialPort, SIGNAL(readyRead()), this, SLOT(onSerialPortReadyRead()));

    m_timer = new QTimer(this);
    m_timer->connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimerTimeout()));
}

void MainWindow::keyPressEvent(QKeyEvent *event)
{
    switch (event->key()) {
        case Qt::Key_Up:
            m_myOpenGLWidget->setPitch(m_myOpenGLWidget->pitch() - 10);
            m_myOpenGLWidget->update();
            break;
        case Qt::Key_Down:
            m_myOpenGLWidget->setPitch(m_myOpenGLWidget->pitch() + 10);
            m_myOpenGLWidget->update();
            break;
        case Qt::Key_Left:

            if (event->modifiers() & Qt::ControlModifier)
                m_myOpenGLWidget->setRoll(m_myOpenGLWidget->roll() - 10);
            else
                m_myOpenGLWidget->setYaw(m_myOpenGLWidget->yaw() - 10);

            m_myOpenGLWidget->update();
            break;
        case Qt::Key_Right:

            if (event->modifiers() & Qt::ControlModifier)
                m_myOpenGLWidget->setRoll(m_myOpenGLWidget->roll() + 10);
            else
                m_myOpenGLWidget->setYaw(m_myOpenGLWidget->yaw() + 10);

            m_myOpenGLWidget->update();
            break;


    }
}

void MainWindow::onOpen()
{
    static bool working = false;

    if (!working) {

        if (m_serialPort->isOpen()) {
            m_serialPort->close();
            m_serialPort->clear();
        }

        if (m_cbxPortList->count() == 0) {
            QMessageBox::warning(this, tr("Waring"), tr("No serial port."));
            return;
        }

        int parity = m_cbxParityList->currentData().toInt();
        int stopBits = m_cbxStopBitsList->currentData().toInt();

        m_serialPort->setPortName(m_cbxPortList->currentText());
        m_serialPort->setBaudRate(m_cbxBaudrateList->currentText().toInt(), QSerialPort::AllDirections);
        m_serialPort->setDataBits((QSerialPort::DataBits)m_cbxDataBitsList->currentText().toInt());
        m_serialPort->setParity((QSerialPort::Parity)parity);
        m_serialPort->setStopBits((QSerialPort::StopBits)stopBits);
        m_serialPort->setFlowControl(QSerialPort::NoFlowControl);

        if (!m_serialPort->open(QIODevice::ReadWrite)) {
            QMessageBox::warning(this, "Error", "Failed to open serial port.");
            return;
        }

        m_timer->start(1000 / 30);

        m_openAction->setText(tr("Close"));
        working = true;
    }
    else {
        m_timer->stop();
        m_serialPort->close();
        m_serialPort->clear();

        m_openAction->setText(tr("Open"));
        working = false;
    }
}

void MainWindow::onTimerTimeout()
{
    m_myOpenGLWidget->update();

    QString attitude = QString(tr("Pitch %1 \tRoll %2 \tYaw %3"))
            .arg(m_myOpenGLWidget->pitch())
            .arg(m_myOpenGLWidget->roll())
            .arg(m_myOpenGLWidget->yaw());

    m_lblAttitude->setText(attitude);
}

void MainWindow::onSerialPortReadyRead()
{
    if (!m_serialPort->canReadLine())
        return;

    QString s = QString(m_serialPort->readLine());

    s = s.trimmed();

    if (s.isNull() || s.isEmpty())
        return;

    QStringList items = s.split(',');
    if (items.count() < 2)
        return;

    bool ok = false;

    float pitch = items[0].toFloat(&ok);
    if (!ok)
        return;

    float roll = items[1].toFloat(&ok);
    if (!ok)
        return;

    float yaw = 0;
    if (items.count() >= 3) {
        yaw = items[2].toFloat(&ok);
        if (!ok)
            return;
    }

    //qDebug() << pitch << roll << yaw;

    m_myOpenGLWidget->setPitch(-pitch);
    m_myOpenGLWidget->setRoll(-roll);
    m_myOpenGLWidget->setYaw(yaw);
}

MainWindow::~MainWindow()
{
    if (m_serialPort) {
        if (m_serialPort->isOpen())
            m_serialPort->close();
        delete m_serialPort;
    }
}

